/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-02-20
*/
package com.rzico.order.controller.admin;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rzico.base.BaseController;
import com.rzico.base.CommResult;
import com.rzico.basics.entity.Enterprise;
import com.rzico.basics.entity.Product;
import com.rzico.basics.entity.Supplier;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.ProductService;
import com.rzico.basics.service.SupplierService;
import com.rzico.core.entity.SysEmployee;
import com.rzico.core.entity.SysOffice;
import com.rzico.core.entity.SysReport;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.*;
import com.rzico.entity.PageResult;
import com.rzico.entity.Pageable;
import com.rzico.exception.CustomException;
import com.rzico.order.entity.Purchase;
import com.rzico.order.entity.PurchaseItem;
import com.rzico.order.service.PurchaseItemService;
import com.rzico.order.service.PurchaseService;
import com.rzico.util.HttpUtils;
import com.rzico.util.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.jasperreports.engine.JRException;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 采购单控制层
 * 正向流程
 * 1、新增，“未确认”
 * 2、确认，生成应付账款
 * 3、收货入库，生成入库单并自动入库，并回写采购单的入库数量
 * 4、入库单入库，回写订单状态“已完成”
 *
 * 反向流程：从入库单发起
 * 1、取消入库
 * 2、作废入库单，回写采购单的入库数量
 * 3、采购单取消确认(需要校验入库单是否作废，并校验应付款是否付款，有则，付款单退款，并删除应付款单)，
 *    采购单变成“未确认”
 * 4、删除未确认采购单
 *
 *
 * @author Rzico Boot
 * @version 1.0
 * @date 2020-02-20
 */
@Api(description = "采购单接口")
@RestController
@RequestMapping("/admin/purchase")
public class PurchaseAdminController extends BaseController {

    @Value("${rzico.filePath.windows}")
    private String windowsFilePath;

    @Value("${rzico.filePath.linux}")
    private String linuxFilePath;

    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private PurchaseItemService purchaseItemService;

    @Autowired
    private ProductService productService;

    @Autowired
    private SysSequenceService sysSequenceService;

    @Autowired
    private SysOfficeService sysOfficeService;

    @Autowired
    protected SysUserService sysUserService;

    @Autowired
    protected SysEmployeeService sysEmployeeService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private SysReportService sysReportService;

    /**
     * 分页查询采购单
     *
     * @return
    */
    @ApiOperation("分页查询采购单")
    @GetMapping("/list")
    @ApiImplicitParams({@ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "String", paramType = "query") ,
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "supplierId", value = "供应商Id", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "productId", value = "商品ID", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "sn", value = "采购单号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "orderStatus", value = "采购单状态", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "paymentStatus", value = "付款状态", dataType = "Integer", paramType = "query")
    })
    public CommResult<Purchase> list(Date startDate, Date endDate, String sn,Long supplierId,Long productId, Integer orderStatus,
                                     Integer paymentStatus, Pageable pageable) {
        Map<String, Object> params = new HashMap<String, Object>();
        params = buildSortField(params, pageable);
        if (startDate!=null){
            params.put("startDate", DateUtils.truncate(startDate, Calendar.DATE));
        }
        if (endDate!=null){
            params.put("endDate", DateUtils.addMilliseconds(DateUtils.addDays(endDate,1),-1));
        }
        if (StringUtils.isNotEmpty(sn)){
            params.put("sn", sn);
        }
        if (null != orderStatus){
            params.put("orderStatus", orderStatus);
        }
        if (null != paymentStatus){
            params.put("paymentStatus", paymentStatus);
        }
        if (null != supplierId){
            params.put("supplierId", supplierId);
        }
        if (null != productId){
            Product product = productService.findById(productId);
            params.put("goodsId", product.getGoodsId());
        }
        params.put("deleted", false);


        Enterprise enterprise = enterpriseService.getCurrent();
        if (enterprise!=null) {
            params.put("enterpriseId", enterprise.getId());
        } else {
            return CommResult.error("没有开通企业");
        }


        //非管理员都启用数据权限
//        SysUser sysUser = sysUserService.getCurrent();
//        if (!sysUserService.isAdmin(sysUser)) {
//            params.put("dataScopeId",sysUser.getId());
//        }


        Page<Object> startPage = PageHelper.startPage(pageable.getPageNum(), pageable.getPageSize());
        List<Purchase> list = purchaseService.selectList(params);
        PageResult<Purchase> pageResult = new PageResult<Purchase>(list, startPage.getTotal(), pageable);
        return CommResult.success(pageResult);
    }

    /**
     * 查询单条采购单
     *
     * @return
    */
    @ApiOperation("查询单条采购单")
    @GetMapping("/find/{id}")
    public CommResult<Purchase> find(@PathVariable Long id) {
        Purchase result = purchaseService.findById(id);

        result.setItemList(purchaseItemService.getItemList(id));

        Map<String,Object> data = new HashMap<>();
        data.put("purchase",result);

        if (result.getOfficeId()!=null && !"".equals(result.getOfficeId())) {
            SysOffice sysOffice = sysOfficeService.selectByPrimaryKey(result.getOfficeId());
            if (sysOffice!=null) {
                data.put("officeName", sysOffice.getName());
            } else {
                data.put("officeName", "无");
            }
        } else {
            data.put("officeName", "无");
        }
        if (result.getOperatorId()!=null) {
            SysEmployee sysUser = sysEmployeeService.selectByPrimaryKey(result.getOperatorId());
            if (sysUser!=null) {
                data.put("operatorName", sysUser.getName());
            } else {
                data.put("operatorName", "无");
            }
        } else {
            data.put("operatorName", "无");
        }
        if (result.getSupplierId()!=null) {
            Supplier supplier = supplierService.selectByPrimaryKey(result.getSupplierId());
            data.put("supplierName", supplier.getName());
        }
        return CommResult.success(data);

    }

    /**
     * 保存采购单
     *
     * @param purchase
     * @return
     */
    @ApiOperation("保存采购单")
    @PostMapping("/save")
    public CommResult<Purchase> save(@RequestBody Purchase purchase) {
        Assert.notNull(purchase.getSupplierId(), "供应商为空");
        purchase.setSn(sysSequenceService.generate("purchase"));

        int affectCount = purchaseService.insertPurchase(purchase);
        if (affectCount <= 0) {
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(purchase.getId());
        return CommResult.success(result);
    }


    /**
     * 保存采购单
     *
     * @param purchase
     * @return
     */
    @ApiOperation("保存并确认")
    @PostMapping("/saveAndConfirm")
    public CommResult<Purchase> saveAndConfirm(@RequestBody Purchase purchase) {
        Assert.notNull(purchase.getSupplierId(), "供应商为空");
        purchase.setSn(sysSequenceService.generate("purchase"));

        int affectCount = purchaseService.saveAndConfirm(purchase);
        if (affectCount <= 0) {
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(purchase.getId());
        return CommResult.success(result);
    }


    /**
     * 保存并入库
     * 该功能为一次性全部入库
     * @param purchase
     * @return
     */
    @ApiOperation("保存并入库")
    @PostMapping("/saveAndInStock")
    public CommResult<Purchase> saveAndInStock(@RequestBody Purchase purchase) {
        Assert.notNull(purchase.getSupplierId(), "供应商为空");
        Assert.notNull(purchase.getShopId(), "入库仓库为空");
        purchase.setSn(sysSequenceService.generate("purchase"));

        int affectCount = purchaseService.saveAndInStock(purchase);
        if (affectCount <= 0) {
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(purchase.getId());
        return CommResult.success(result);
    }

    /**
     * 批量删除采购单
     *
     * @param ids
     * @return
     */
    @ApiOperation("批量删除采购单,ids用逗号拼接")
    @PostMapping("/del/{ids}")
    public CommResult<Purchase> del(@PathVariable String ids) {

        try {
            purchaseService.deleteByIds(ids.split(","));
        } catch (Exception e) {
            return CommResult.error(e.getMessage());
        }
        return CommResult.success();
    }

    /**
     * 更新采购单
     *
     * @param purchase
     * @return
     */
    @ApiOperation("更新采购单")
    @PostMapping("/update")
    public CommResult<Purchase> update(@RequestBody Purchase purchase) {
        Assert.notNull(purchase.getId(), "ID为空");
        int affectCount = purchaseService.update(purchase);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(purchase.getId());
        return CommResult.success(result);
    }


    /**
     * 确认采购单
     *
     * @param orderId
     * @return
     */
    @ApiOperation("确认采购单")
    @PostMapping("/confirm/{orderId}")
    public CommResult<Purchase> confirm(@PathVariable Long orderId) {
        Purchase purchase = new Purchase();
        purchase.setId(orderId);
        int affectCount = purchaseService.confirm(purchase);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(purchase.getId());
        return CommResult.success(result);
    }


    /**
     * 流程：
     * 1、前端按钮：“已完成”订单，取消确认按钮不显示
     * 2、后台功能：支持“已完成”“已确认”状态的订单取消确认成“未确认”
     *
     * 取消确认采购单，不能有已付款的应付款、入库单必须作废
     *
     * @param id
     * @return
     */
    @ApiOperation("取消确认采购单")
    @PostMapping("/unconfirm/{id}")
    public CommResult<Purchase> unconfirm(@PathVariable Long id) {
        int affectCount = purchaseService.unconfirm(id);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(id);
        return CommResult.success(result);
    }

    /**
     * 采购入库
     *
     * @param orderId 采购单ID
     * @param shopId 入库仓库ID
     * @param list
     * @return
     */
    @ApiOperation("采购单分批入库")
    @PostMapping("/inStock/{orderId}")
    public CommResult<Purchase> batchInStock(@PathVariable Long orderId, Long shopId, Date orderDate, @RequestBody List<PurchaseItem> list) {
        if (shopId==null) {
            return CommResult.error("发货仓库不能为空");
        }
        if (orderDate==null) {
            return CommResult.error("发货日期不能为空");
        }
        purchaseService.batchInStock(orderId, shopId, sysSequenceService.generate("warehouse"), orderDate,list);
        Purchase result = purchaseService.findById(orderId);
        return CommResult.success(result);
    }


    /**
     * 采购单分批入库并自动入库
     *
     * @param orderId 采购单ID
     * @param shopId 入库仓库ID
     * @param list
     * @return
     */
    @ApiOperation("采购单分批入库并自动入库")
    @PostMapping("/inStockAndAudit/{orderId}")
    public CommResult<Purchase> inStockAndAudit(@PathVariable Long orderId, Long shopId, Date orderDate, @RequestBody List<PurchaseItem> list) {
        if (shopId==null) {
            return CommResult.error("发货仓库不能为空");
        }
        if (orderDate==null) {
            return CommResult.error("发货日期不能为空");
        }
        int affectCount = purchaseService.inStockAndAudit(orderId, shopId,sysSequenceService.generate("warehouse"), orderDate,list);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(orderId);
        return CommResult.success(result);
    }

    /**
     * 采购退货
     *
     * @param list
     * @return
     */
    @ApiOperation("采购退货申请")
    @PostMapping("/returns/{orderId}")
    public CommResult<Purchase> batchReturns(@PathVariable Long orderId, Long shopId, Date orderDate, @RequestBody List<PurchaseItem> list) {
        if (shopId==null) {
            return CommResult.error("退货仓库不能为空");
        }
        if (orderDate==null) {
            return CommResult.error("退货日期不能为空");
        }
        int affectCount = purchaseService.batchOutStock(orderId, shopId, sysSequenceService.generate("warehouse"), orderDate,list);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(orderId);
        return CommResult.success(result);
    }



    /**
     * 流程：
     * 1、前端按钮，在“未确认”、“已确认”状态下会显示
     * 2、后台不控制作废时的状态，“已完成”状态也可以作废；尚未付款的采购单可以作废，若已付款，请先关闭付款单
     * 操作权限：管理员、制单人员有权限作废
     * @param id
     * @return
     *
     *
     * 次方法不用，作废
     *
     */
/*    @ApiOperation("作废")
    @PostMapping("/cancel/{id}")
    public CommResult<Purchase> cancel(@PathVariable Long id) {
        int affectCount = purchaseService.cancel(id);
        if (affectCount <= 0){
            return CommResult.error();
        }
        Purchase result = purchaseService.findById(id);
        return CommResult.success(result);
    }*/


    /**
     *  订单打印
     *
     * @param id
     * @return
     */
    @ApiOperation("打印")
    @GetMapping("/print/{id}")
    public void print(HttpServletRequest request, HttpServletResponse response, @PathVariable String id)
            throws ClassNotFoundException, SQLException, JRException, IOException, IllegalAccessException{
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>订单打印 start<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        Map<String, Object> param = new HashMap<String, Object>();
        param = HttpUtils.requestParam(request);

        Purchase purchase = purchaseService.selectByPrimaryKey(id);
        if (null == purchase){
            throw new CustomException("采购单不存在");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Enterprise enterprise = enterpriseService.selectByPrimaryKey(purchase.getEnterpriseId());
        if (null == enterprise) {
            throw new CustomException("没有开通企业");
        }
        SysOffice sysOffice = sysOfficeService.findById(purchase.getOfficeId());
        if (null != sysOffice){
            param.put("officeName",sysOffice.getOfficeName());
        }
        param.put("COMPANY",enterprise.getName());
        param.put("enterpriseId",enterprise.getId());
        param.put("consignee", purchase.getConsignee());
        param.put("address", purchase.getAddress());
        param.put("phone", purchase.getPhone());
        param.put("orderDate", sdf.format(purchase.getOrderDate()));
        param.put("memo", purchase.getMemo());
        param.put("sn", purchase.getSn());

        logger.info("打印报表查询参数：{}", param.toString());

        String fileName = enterprise.getMchId()+"_"+purchase.getSn() + ".jasper";
        //fileName就是sys_report表的id
        SysReport sysReport = sysReportService.selectByPrimaryKey(fileName);

        String filePath = "";
        if (System.getProperty("os.name").contains("Windows")) {
            filePath = windowsFilePath;
        } else if (System.getProperty("os.name").contains("Linux")) {
            filePath = linuxFilePath;
        }
        //检查服务器上是否存在模板
        File file = new File(filePath + File.separator + fileName);
        if (!file.exists()){
            try {
                String url = sysReport == null?"":sysReport.getTemplate();
                sysReportService.fileDownLoad(response, url, filePath, fileName);
            } catch (Exception e){
                logger.info("打印模板下载失败");
                throw new CustomException("打印模板下载失败");
            }
        }


        String reportName = "purchasePrint";
        param.put("REPORT_NAME","采购单");
        StringBuffer sql = new StringBuffer();
        sql.append(" SELECT b.sn,b.name,b.spec,b.cost,b.unit, ");
        sql.append("    b.price,b.quantity,round(b.price*b.quantity, 2) as amount,b.discount FROM wx_purchase_item b ");
        sql.append(" WHERE b.purchase_id = "+id);

        File file2 = new File(filePath + File.separator + fileName);
        if (!file2.exists()) {
            //下载之后还不存在，就使用classpath路径的模板
            sysReportService.ReportToPdfBySql(reportName, param, sql.toString(), response);
        }else{
            sysReportService.commReportToPdf(filePath, fileName, param, sql.toString(), response);
        }
    }


    /**
     *  订单打印
     *
     * @param id
     * @return
     */
    @ApiOperation("导出")
    @GetMapping("/export/{id}")
    public void export(HttpServletRequest request, HttpServletResponse response, @PathVariable String id)
            throws ClassNotFoundException, SQLException, JRException, IOException, IllegalAccessException{
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>订单打印 start<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        Map<String, Object> param = new HashMap<String, Object>();
        param = HttpUtils.requestParam(request);

        Purchase purchase = purchaseService.selectByPrimaryKey(id);
        if (null == purchase){
            throw new CustomException("采购单不存在");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Enterprise enterprise = enterpriseService.selectByPrimaryKey(purchase.getEnterpriseId());
        if (null == enterprise) {
            throw new CustomException("没有开通企业");
        }
        SysOffice sysOffice = sysOfficeService.findById(purchase.getOfficeId());
        if (null != sysOffice){
            param.put("officeName",sysOffice.getOfficeName());
        }
        param.put("COMPANY",enterprise.getName());
        param.put("enterpriseId",enterprise.getId());
        param.put("consignee", purchase.getConsignee());
        param.put("address", purchase.getAddress());
        param.put("phone", purchase.getPhone());
        param.put("orderDate", sdf.format(purchase.getOrderDate()));
        param.put("memo", purchase.getMemo());
        param.put("sn", purchase.getSn());

        logger.info("打印报表查询参数：{}", param.toString());

        String reportName = "purchasePrint";
        param.put("REPORT_NAME","采购单");
        StringBuffer sql = new StringBuffer();
        sql.append(" SELECT b.sn,b.name,b.spec,b.cost,b.unit, ");
        sql.append("    b.price,b.quantity,round(b.price*b.quantity, 2) as amount,b.discount FROM wx_purchase_item b ");
        sql.append(" WHERE b.purchase_id = "+id);

        sysReportService.ReportToExcelBySql(reportName, param, sql.toString(), response);
    }
}
